package com.enki.cigarettes.controller;

import com.enki.cigarettes.controller.vo.response.CouponResponseVo;
import com.enki.cigarettes.controller.vo.response.InitOrderResponseVo;
import com.enki.cigarettes.controller.vo.response.UserCouponResponseVo;
import com.enki.cigarettes.entity.*;
import com.enki.cigarettes.enums.CouponEnums;
import com.enki.cigarettes.enums.ProductEnums;
import com.enki.cigarettes.handler.Response;
import com.enki.cigarettes.repository.*;
import com.enki.cigarettes.statics.StaticKeys;
import com.enki.cigarettes.utils.DateUtils;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * @author WCS.Wang
 * @version V1.0
 * @Package com.enki.cigarettes.controller
 * @Name e-cigarettes-shop-api-module
 * @Description: TODO 用户优惠券
 * @date 2019-07-25
 */
@RestController
@RequestMapping("/api/user/coupons")
@Slf4j
public class UserCouponController {


    @Autowired
    CartTRepository cartTRepository;
    @Autowired
    ProductTRepository productTRepository;
    @Autowired
    ProductSkuTRepository productSkuTRepository;
    @Autowired
    UserCouponTRepository userCouponTRepository;
    @Autowired
    CouponTRepository couponTRepository;
    @Autowired
    UserTRepository userTRepository;

    @ApiOperation(value = "获取可用优惠券")
    @ApiImplicitParam(name = "id", value = "购物车ID", dataType = "String", required = true)
    @GetMapping(value = "/available/{id}/{source}")
    public Object findAvailableCoupons(@PathVariable String id,HttpSession session) {
        try {
            Object sessionId = session.getAttribute(StaticKeys.USER_ID);
            if (sessionId == null) {
                return Response.unauthorized_401("登录身份失效，请重新登录");
            }
            UserT userBean = userTRepository.findOneById(sessionId.toString());
            if(userBean == null) {
                return Response.badRequest_400("登录身份失效，请重新登录");
            }
            String[] cartIds = id.split(StaticKeys.SPLIT);
            // 总金额
            int totalAmount = 0;
            for (String cartId : cartIds) {
                CartT cartBean = cartTRepository.findOneByIdAndUserTId(cartId, sessionId.toString());
                if (cartBean != null) {
                    ProductT productBean = productTRepository.findOneByIdAndStatus(cartBean.getProductTId(), ProductEnums.ProductStatus.ONTHSHELF.getType());
                    // 如果此商品不存在跳出当前循环
                    if (productBean == null) {
                        continue;
                    }
                    ProductSkuT productSkuBean = productSkuTRepository.findOneByIdAndStatus(cartBean.getProductSkuTId(), ProductEnums.ProductSkuStatus.ONTHESHELF.getType());
                    // 如果此商品sku不存在跳出当前循环
                    if (productSkuBean == null) {
                        continue;
                    }
                    totalAmount += cartBean.getQuantity() * productSkuBean.getSalePrice();
                }
            }
            final int checkRealPrice = totalAmount;
            Specification<UserCouponT> specification = new Specification<UserCouponT>() {
                @Override
                public Predicate toPredicate(Root<UserCouponT> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                    List<Predicate> predicateList = new ArrayList<>();
                    Root<CouponT> couponTRoot = query.from(CouponT.class);
                    predicateList.add(criteriaBuilder.equal(root.get("userId"), sessionId.toString()));
                    predicateList.add(criteriaBuilder.equal(root.get("status"), false));
                    predicateList.add(criteriaBuilder.equal(couponTRoot.get("id"), root.get("couponTId")));
                    predicateList.add(criteriaBuilder.equal(couponTRoot.get("status"), true));
                    predicateList.add(criteriaBuilder.greaterThan(couponTRoot.get("effectiveEndTime"), new Date()));
                    predicateList.add(criteriaBuilder.lessThanOrEqualTo(couponTRoot.get("couponMoney"), checkRealPrice));
                    predicateList.add(criteriaBuilder.equal(couponTRoot.get("source"), userBean.getUserSource()));
                    Predicate[] predicates = new Predicate[predicateList.size()];
                    query.where(predicateList.toArray(predicates));
                    return query.getRestriction();
                }
            };
            List<UserCouponT> couponBeanList = userCouponTRepository.findAll(specification);
            List<UserCouponResponseVo> couponVoItems = new ArrayList<>();
            for (UserCouponT bean : couponBeanList) {
                CouponT couponBean = couponTRepository.findOneById(bean.getCouponTId());
                if (couponBean != null) {
                    UserCouponResponseVo vo = new UserCouponResponseVo();
                    vo.setId(bean.getId());
                    vo.setName("满" + Double.valueOf(couponBean.getCouponMoney()) / 100 + "减去" + Double.valueOf(couponBean.getCouponPrice()) / 100);
                    vo.setCouponPrice(Double.valueOf(couponBean.getCouponPrice()) / 100 + "");
                    vo.setCouponMoney(Double.valueOf(couponBean.getCouponMoney()) / 100 + "");
                    couponVoItems.add(vo);
                }
            }
            return Response.success(couponVoItems, StaticKeys.SUCCESS);
        } catch (Exception e) {
            log.error("获取可用优惠券失败：" + e.getMessage());
            e.printStackTrace();
            return Response.serverError_500("获取可用优惠券失败");
        }
    }

    @ApiOperation(value = "计算优惠信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "优惠券ID", dataType = "String", required = true),
            @ApiImplicitParam(name = "cartIds", value = "购物车ID，使用','拼接", dataType = "String", required = true)
    })
    @GetMapping(value = "/calculation/{id}/{cartIds}")
    public Object calculation(@PathVariable String id, @PathVariable String cartIds, HttpSession session) {
        try {
            Object sessionId = session.getAttribute(StaticKeys.USER_ID);
            if (sessionId == null) {
                return Response.unauthorized_401("登录身份失效，请重新登录");
            }
            Map<String, Object> responseData = new HashMap<>();
            // 总金额
            String[] cartIdItems = cartIds.split(StaticKeys.SPLIT);
            int totalAmount = 0;
            for (String cartId : cartIdItems) {
                CartT cartBean = cartTRepository.findOneByIdAndUserTId(cartId, sessionId.toString());
                if (cartBean != null) {
                    ProductT productBean = productTRepository.findOneByIdAndStatus(cartBean.getProductTId(), ProductEnums.ProductStatus.ONTHSHELF.getType());
                    // 如果此商品不存在跳出当前循环
                    if (productBean == null) {
                        continue;
                    }
                    ProductSkuT productSkuBean = productSkuTRepository.findOneByIdAndStatus(cartBean.getProductSkuTId(), ProductEnums.ProductSkuStatus.ONTHESHELF.getType());
                    // 如果此商品sku不存在跳出当前循环
                    if (productSkuBean == null) {
                        continue;
                    }
                    totalAmount += cartBean.getQuantity() * productSkuBean.getSalePrice();
                }
            }
            // 计算优惠金额
            int discountAmount = 0;
            UserCouponT userCouponBean = userCouponTRepository.findOneByIdAndUserId(id, sessionId.toString());
            if (userCouponBean != null) {
                CouponT coupon = couponTRepository.findOneById(userCouponBean.getCouponTId());
                if (coupon != null) {
                    discountAmount = coupon.getCouponPrice();
                    if (totalAmount < coupon.getCouponMoney()) {
                        return Response.badRequest_400("不满足满减条件");
                    }
                    UserCouponResponseVo vo = new UserCouponResponseVo();
                    vo.setId(userCouponBean.getId());
                    vo.setName("满" + Double.valueOf(coupon.getCouponMoney()) / 100 + "减去" + Double.valueOf(coupon.getCouponPrice()) / 100);
                    vo.setCouponPrice(Double.valueOf(coupon.getCouponPrice()) / 100 + "");
                    vo.setCouponMoney(Double.valueOf(coupon.getCouponMoney()) / 100 + "");
                    responseData.put("bean", vo);
                }
            }
            // 应支付金额
            double shouldAmount = Double.valueOf(totalAmount - discountAmount) / 100;
            responseData.put("shouldAmount", shouldAmount);
            return Response.success(responseData, StaticKeys.SUCCESS);
        } catch (Exception e) {
            log.error("计算优惠信息失败：" + e.getMessage());
            e.printStackTrace();
            return Response.serverError_500("计算优惠信息失败");
        }
    }

    @ApiOperation(value = "我的优惠券")
    @GetMapping
    public Object findMyCoupons(HttpSession session) {
        try {
            Object sessionId = session.getAttribute(StaticKeys.USER_ID);
            if (sessionId == null) {
                return Response.unauthorized_401("登录身份失效，请重新登录");
            }
            UserT userBean = userTRepository.findOneById(sessionId.toString());
            if(userBean == null) {
                return Response.badRequest_400("登录身份失效，请重新登录");
            }
            Specification<UserCouponT> specification = new Specification<UserCouponT>() {
                @Override
                public Predicate toPredicate(Root<UserCouponT> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                    List<Predicate> predicateList = new ArrayList<>();
                    Root<CouponT> couponTRoot = query.from(CouponT.class);
                    predicateList.add(criteriaBuilder.equal(root.get("userId"), sessionId.toString()));
                    predicateList.add(criteriaBuilder.equal(root.get("status"), false));
                    predicateList.add(criteriaBuilder.equal(couponTRoot.get("id"), root.get("couponTId")));
                    predicateList.add(criteriaBuilder.equal(couponTRoot.get("status"), true));
                    predicateList.add(criteriaBuilder.greaterThan(couponTRoot.get("effectiveEndTime"), new Date()));
                    predicateList.add(criteriaBuilder.equal(couponTRoot.get("source"), userBean.getUserSource()));
                    Predicate[] predicates = new Predicate[predicateList.size()];
                    query.where(predicateList.toArray(predicates));
                    return query.getRestriction();
                }
            };
            List<UserCouponT> couponBeanList = userCouponTRepository.findAll(specification);
            List<CouponResponseVo> couponItems = new ArrayList<>();
            for (UserCouponT bean : couponBeanList) {
                CouponT couponBean = couponTRepository.findOneById(bean.getCouponTId());
                if (couponBean != null) {
                    CouponResponseVo couponItem = new CouponResponseVo();
                    BeanUtils.copyProperties(couponBean, couponItem);
                    couponItem.setTypeName(CouponEnums.CouponType.getName(couponBean.getType()));
                    couponItem.setCouponScopeName(CouponEnums.CouponScope.getName(couponBean.getCouponScope()));
                    Double percentage = (Double.valueOf(couponBean.getCouponAmount()) / Double.valueOf(couponBean.getCouponCount())) * 100;
                    couponItem.setPercentage(percentage.intValue());
                    couponItem.setId(bean.getId());
                    couponItem.setUseTime(DateUtils.getDateYMD(couponBean.getEffectiveStartTime()) + " - " + DateUtils.getDateYMD(couponBean.getEffectiveEndTime()));
                    couponItems.add(couponItem);
                }
            }
            return Response.success(couponItems, StaticKeys.SUCCESS);
        } catch (Exception e) {
            log.error("获取可用优惠券失败：" + e.getMessage());
            e.printStackTrace();
            return Response.serverError_500("获取可用优惠券失败");
        }
    }

}
